package com.express.gateway.verticle;

import com.express.gateway.common.EventBusTopicConst;
import com.express.gateway.common.ResultFormat;
import com.express.gateway.common.util.StrUtil;
import com.express.gateway.manage.auth.RolesConstant;
import com.express.gateway.manage.auth.UserAuthUtil;
import com.express.gateway.manage.enums.ContentTypeEnum;
import com.express.gateway.manage.enums.StatusCodeEnum;
import io.vertx.core.*;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.ResponseContentTypeHandler;
import io.vertx.ext.web.handler.StaticHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * Exp-Inlet的CURL客户端Verticle,
 *
 * @author flower
 */
public class ClientCurlVerticle extends AbstractVerticle {
    private static final Logger LOG = LogManager.getLogger(ClientCurlVerticle.class);

    /**
     * 返回的CONTENT_TYPE值JSON
     */
    private final String CONTENT_VALUE_JSON_UTF8 = ContentTypeEnum.JSON_UTF8.val();

    @Override
    public void start(Promise<Void> fut) throws Exception {
        LOG.info("Start CurlClient Verticle");
        Router router = Router.router(vertx);
        router.route().handler(BodyHandler.create());
        router.route().handler(StaticHandler.create());
        router.route().handler(ResponseContentTypeHandler.create());
        // 通过curl的方式创建网关应用
        router.route("/curl/findAPP").produces(CONTENT_VALUE_JSON_UTF8).handler(this::findAppByCurl);
        vertx.createHttpServer().requestHandler(router).listen(5053, res -> {
            if (res.succeeded()) {
                LOG.info("The ClientCurlVerticle Running on port 5053");
                fut.complete();
            } else {
                LOG.error("The ClientCurlVerticle start fail!");
                fut.fail(res.cause());
            }
        });
    }

    /**
     * 查看所有应用网关,通过curl的方式
     *
     * @param rct
     */
    public void findAppByCurl(RoutingContext rct) {
        String user = rct.request().getParam("user");
        String pwd = rct.request().getParam("pwd");
        LOG.info("[ip: {},user: {}] 访问curl模式->查看所有应用网关", rct.request().remoteAddress(), user);
        if (!StrUtil.isNullOrEmpty(user, pwd)) {
            rct.response().end(ResultFormat.formatAsZero(StatusCodeEnum.C1400));
            return;
        }
        JsonObject authInfo = new JsonObject();
        authInfo.put(RolesConstant.USER_NAME_KEY, user);
        authInfo.put(RolesConstant.USER_PWD_KEY, pwd);
        authInfo.put(RolesConstant.USER_ROLE_KEY, RolesConstant.READ);
        Future.<Boolean>future(auth -> {
            // 进行用户权限认证
            UserAuthUtil.auth(authInfo, vertx, auth);
        }).compose((auth) -> Future.<JsonArray>future(findApp -> {
            checkUserAndApps(rct, auth, findApp, user);
        })).onComplete(res -> {
            processBusinessData(rct, res, user);
        });
    }


    private void checkUserAndApps(RoutingContext rct, Boolean auth, Promise<JsonArray> findApp, String user) {
        LOG.info("[user: " + user + "] 访问curl模式->查看所有应用网关 鉴权结果: " + auth);
        // 检查用户权限并查询所有应用网关
        if (!auth) {
            LOG.error("user can't access, token is null!");
            rct.response().end(ResultFormat.formatAsZero(StatusCodeEnum.C401));
            findApp.fail("Exp-Inlet Manual response");
            return;
        }
        vertx.eventBus().<JsonArray>request(EventBusTopicConst.FIND_APP, null, reply -> {
            if (reply.succeeded()) {
                findApp.complete(reply.result().body());
            } else {
                findApp.fail(reply.cause());
            }
        });
    }


    private static void processBusinessData(RoutingContext rct, AsyncResult<JsonArray> res, String user) {
        LOG.info("[user:" + user + "] 访问curl模式->查看所有应用网关 执行结果: " + res.succeeded());
        // 统一失败处理与创建文件是否成功!
        if (res.succeeded()) {
            JsonArray result = res.result();
            rct.response().end(ResultFormat.format(StatusCodeEnum.C200, result));
            return;
        }
        if (res.cause() != null && !(res.cause().getMessage().contains("Exp-Inlet Manual response"))) {
            LOG.error("[user:" + user + "] 访问curl模式->查看所有应用网关 异常:" + res.cause());
        }
        if (res.cause() == null) {
            rct.response().end(ResultFormat.formatAsZero(StatusCodeEnum.C1000));
        } else if (res.cause().getMessage().contains("Exp-Inlet Manual response")) {
        } else {
            rct.response().end(ResultFormat.format(StatusCodeEnum.C500, res.cause().toString()));
        }
    }

    /**
     * 读取文件JsonObject文件并返回
     *
     * @param path
     * @param handler
     */
    public void readFile(String path, Handler<AsyncResult<JsonObject>> handler) {
        vertx.fileSystem().readFile(path, fileRes -> {
            try {
                JsonObject result = fileRes.result().toJsonObject();
                handler.handle(Future.<JsonObject>succeededFuture(result));
            } catch (Exception e) {
                handler.handle(Future.failedFuture(e));
            }
        });
    }

}
